#!/usr/bin/python3
# -*- coding: utf-8 -*-

import datetime
import time
import traceback
import json
import msgpackrpc
import uuid
import os

from flask import Flask, g, request, jsonify, render_template, \
    flash, redirect, url_for, session

import rest_log

app = Flask(__name__)
app.secret_key = 'green rseading key'
app.config['SESSION_TYPE'] = 'filesystem'

feature_db_path = "/home/nvidia/.bin/git/registration_online/feature_db.txt";

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        return render_template('index.html')
    else:
        global feature_db_path
        user_name = request.form.get('user_name', '')
        user_name = user_name.strip(' ')
        user_image = request.files.get('user_image', '')
        if not user_name or not user_image or (not user_image.filename.endswith('.jpg') and
                                               not user_image.filename.endswith('.jpeg') and
                                               not user_image.filename.endswith('.png')):
            flash(u'图片需 JPG或PNG 格式', 'error')
            return render_template('index.html')
        client = msgpackrpc.Client(msgpackrpc.Address("localhost", 18080), timeout=20)
        image_data = user_image.read()
        code = ''
        code_int = -1
        feature_str = ''
        try:
            code = client.call('registration_image', image_data, 0)
            code_int = int(code)
            print(code)
            if code_int == 1:
                flash(u'没有检测到人脸', 'error')
            elif code_int == 2:
                flash(u'检测到多张人脸', 'error')
            elif code_int == 3:
                flash(u'人脸区域太小', 'error')
            elif code_int == 4:
                flash(u'检测到侧脸', 'error')
            else:
                flash(u'未知错误', 'error')
            return render_template('index.html')
        except ValueError as e:
            pass
        except Exception as e:
            print(e)
            flash(u'注册失败: ' + str(e), 'error')
            return render_template('index.html')
        feature_db_file = open(feature_db_path, 'a')
        image_save_name = str(uuid.uuid4()).replace('-', '') + '_' + user_image.filename
        image_save_path = '/home/nvidia/.bin/git/registration_server/src/static/image/' + image_save_name
        image_save_file = open(image_save_path, 'wb')
        image_save_file.write(image_data)
        image_save_file.close()
        feature_db_file.write(user_name + ' ' + 'image/' + image_save_name + '\n')
        feature_db_file.write(code.decode("utf-8") + '\n')
        feature_db_file.close()
        code = client.call('registration_image', b'', 1)
        flash(u'注册成功', 'success')
        return render_template('index.html')


@app.route('/user_feature', methods=['GET', 'POST'])
def user_feature():
    global feature_db_path
    try:
        feature_db_file = open(feature_db_path, 'r')
    except FileNotFoundError:
        flash(u'暂无注册用户', 'success')
        return render_template('user_feature.html', user_info=[])
    all_feature = feature_db_file.read()
    feature_db_file.close()
    user_info = []
    if request.method == 'GET':
        all_feature = all_feature.split('\n')
        for i in range(0, len(all_feature) // 2):
            _feature = {}
            name_feature = all_feature[2*i].split(' ')
            _feature['index'] = i + 1
            _feature['name'] = name_feature[0]
            _feature['image'] = name_feature[1]
            user_info.append(_feature)
        return render_template('user_feature.html', user_info=user_info)
    else:
        feature_id = request.form.get('feature_id', '')
        if not feature_id:
            flash(u'参数错误', 'error')
            return render_template('user_feature.html', user_info=user_info)
        all_feature = all_feature.split('\n')
        feature_index = -1
        for i in range(0, len(all_feature)):
            if feature_id in all_feature[i]:
                feature_index = i
                break
        if feature_index == -1:
            flash(u'参数错误', 'error')
            return render_template('user_feature.html', user_info=user_info)
        os.remove('static/' + all_feature[feature_index].split(' ')[1].strip('\n'))
        all_feature.pop(feature_index)
        all_feature.pop(feature_index)
        all_feature = '\n'.join(all_feature)
        feature_db_file = open(feature_db_path, 'w')
        feature_db_file.write(all_feature)
        feature_db_file.close()
        client = msgpackrpc.Client(msgpackrpc.Address("localhost", 18080), timeout=20)
        code = client.call('registration_image', b'', 1)
        all_feature = all_feature.split('\n')
        for i in range(0, len(all_feature) // 2):
            _feature = {}
            name_feature = all_feature[2*i].split(' ')
            _feature['index'] = i + 1
            _feature['name'] = name_feature[0]
            _feature['image'] = name_feature[1]
            user_info.append(_feature)
        return render_template('user_feature.html', user_info=user_info)


@app.before_request
def before_request():
    g.log_info = dict()
    if 'X-Real-IP' in request.headers:
        g.log_info['remote_addr'] = request.headers['X-Real-IP']
        g.remote_addr = request.headers['X-Real-IP']
    else:
        g.log_info['remote_addr'] = request.headers.get('X-Forwarded-For')
        g.remote_addr = request.headers.get('X-Forwarded-For')
    if not g.remote_addr:
        g.remote_addr = request.remote_addr
    g.log_info['request_data'] = request.data
    g.log_info['method'] = request.method
    g.log_info['url'] = request.url
    g.log_info['headers'] = dict(request.headers)
    g.log_info['form'] = dict(request.form)
    g.log_info['start_time'] = time.time()


@app.after_request
def after_request(response):
    if not getattr(g, 'log_info', None):
        response.headers['Date'] = \
            datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
        return response
    g.log_info['end_time'] = time.time()
    g.log_info['process_time'] = \
        g.log_info['end_time'] - g.log_info['start_time']

    g.log_info['status_code'] = response.status_code
    g.log_info['ret_headers'] = dict(response.headers)

    if 400 <= response.status_code < 500:
        rest_log.logger.warning(g.log_info)
    else:
        if '/static' not in request.url:
            rest_log.logger.info(g.log_info)

    response.headers['Date'] = \
        datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
    return response


@app.errorhandler(404)
def uri_not_found(exception):
    ret = dict()
    ret['code'] = 1000
    ret['error'] = 'uri_not_found'
    ret['request'] = ' '.join([request.method, request.url])
    return jsonify(ret), 404


@app.errorhandler(500)
def internal_server_error(exception):
    ret = dict()
    ret['code'] = 999
    ret['error'] = 'unknown_error'
    ret['request'] = ' '.join([request.method, request.url])
    ret['exception'] = str(exception)
    ret['detail'] = u'服务器维护中'
    return jsonify(ret), 500


@app.teardown_request
def teardown_request(exception):
    if getattr(g, 'log_info', None) is None:
        g.log_info = dict()

    if exception:
        g.log_info['exception'] = str(exception)
        g.log_info['format_exc'] = traceback.format_exc()
        rest_log.logger.critical(g.log_info)


if __name__ == '__main__':
    app.config['DEBUG'] = False
    app.run(host='0.0.0.0', port=2000)
